/**
 * @function xlib-js
 * @encode utf-8
 * @copyright (C) lijun
 * @file core.js
 * @author lijun
 * @version 1.0
 * @date 2009-12-6
 */

/**
 *=================================|
 * 原生对象扩展, String/Object/Date|
 *=================================|
 */

/**
 * 扩展String对象
 * 匹配以prefix开头的字符串
 * @param prefix 匹配字符串
 * @param offset 偏移值
 * @return 是否匹配 true/false
 */
String.prototype.startsWith = function(prefix, offset)
{
    offset = typeof(offset) == "number" ? offset : 0;
    if (this.length >= (prefix.length + offset))
    {
        return (this.substr(offset, prefix.length) == prefix);
    }
    else
    {
        return false;
    }
};

/**
 * 扩展String对象
 * 匹配以suffix结尾的字符串
 * @param suffix 匹配字符串
 * @return 是否匹配 true/false
 */
String.prototype.endsWith = function(suffix)
{
    if (this.length >= suffix.length)
    {
        return (this.substr((this.length - suffix.length), suffix.length) == suffix);
    }
    else
    {
        return false;
    }
};

/**
 * 扩展String对象
 * 替换所有相匹配的字符或字符串
 * @param regexp 匹配表达式
 * @param replacement 替换字符串
 * @return 替换后的字符串,如果没有找到匹配返回原字符串
 */
String.prototype.replaceAll = function(regexp, replacement)
{
    var pattern = new RegExp(regexp, "gm");
    var tmp = this.replace(pattern, replacement);
    pattern = null;
    return tmp;
};

/**
 * 扩展String对象
 * 替换匹配表达式第一次出现的内容
 * @param regexp 匹配表达式
 * @param replacement 替换字符串
 * @return 替换后的字符串,如果没有找到匹配返回原字符串
 */
String.prototype.replaceFirst = function(regexp, replacement)
{
    var group = new RegExp("("+ regexp + ")", "gm").exec(this);
    var tmp = this;
    if (null != group)
    {
        tmp = this.substring(0, group.index)
            .concat(replacement)
            .concat(this.substring(group.index+group[1].length));
    }
    group = null;
    return tmp;
};

/**
 * 扩展String对象
 * 去空字符
 * @return 去空后的字符串
 */
String.prototype.trim = function()
{
    var pattern = /[\s ]+/gmi;
    var tmp = this.replace(pattern, "");
    pattern = null;
    return tmp;
};

/**
 * 扩展String对象
 * 去左空字符
 * @return 去空后的字符串
 */
String.prototype.leftTrim = function()
{
    var pattern = /^[\s ]+/gmi;
    var tmp = this.replace(pattern, "");
    pattern = null;
    return tmp;
};

/**
 * 扩展String对象
 * 去右空字符
 * @return 去空后的字符串
 */
String.prototype.rightTrim = function()
{
    var pattern = /[\s ]+$/gmi;
    var tmp = this.replace(pattern, "");
    pattern = null;
    return tmp;
};

/**
 * 扩展String对象
 * 去两边空字符
 * @return 去空后的字符串
 */
String.prototype.bothTrim = function()
{
    return (this.leftTrim()).rightTrim();
};

/**
 * 扩展String对象
 * 返回实际长度,区分中英文
 * @return 字符串长度
 */
String.prototype.size = function()
{
    return this.replace(/[^\u0000-\u00FF]/gmi, "**").length;
};

/**
 * 填补字符串，前补齐指定位数
 * @param chr 填补字符
 * @param bit 位数
 * @return 填补完后的字符串
 */
String.prototype.fillBefore = function(chr, bit)
{
    var len = this.length;
    var shift = bit - len + 1;
    var str = this;
    if(shift > 0)
    {
        var a = new Array(shift);
        str = a.join(chr) + str;
        a = null;
    }
    return str;
};

/**
 * 填补字符串，前补齐指定位数
 * @param chr 填补字符
 * @param bit 位数
 * @return 填补完后的字符串
 */
String.prototype.fillAfter = function(chr, bit)
{
    var len = this.length;
    var shift = bit - len + 1;
    var str = this;
    if(shift > 0)
    {
        var a = new Array(shift);
        str = str + a.join(chr);
        a = null;
    }
    return str;
};

/**
 * 转换成货币格式
 * @param bit 小数位数
 * @return 返回转换后的字符串
 */
String.prototype.toCurrency = function(bit)
{
    bit = bit || 2;
    var pattern = /^(\-?)(\d+)(\.\d+)?$/;
    var macher = pattern.exec(this);
    var sign = null != macher ? RegExp.$1 : "";
    var integer = null != macher ? RegExp.$2 : "0";
    var decimal = null != macher ? RegExp.$3 : ".00";
    var size = integer.length;
    var mod = size > 3 ? size % 3 : 0;
    var tmp = "";
    var start = 0 == mod ? "" : integer.substr(0, mod) + ",";
    var flag = 0;
    decimal = "" == decimal ? ".00" : decimal;
    decimal = (decimal.fillAfter(0, bit + 1)).substr(0, bit + 1);
    for(var i = mod; i < size; i++)
    {
        tmp += integer.charAt(i);
        flag++;
        if(flag % 3 == 0 && i < size - 1)
        {
            tmp += ",";
            flag = 0;
        }
    }
    pattern = null;
    return sign + start + tmp + decimal;
};

/**
 * 格式化字符串，用对象的键替换成对象的值。
 * @param Object {key:value, key:value}
 * @param String chr
 * @return 格式化后的字符串
 */
String.prototype.format = function(param, chr)
{
    param = param || {};
    chr = chr || "$";
    var tmp = this;
    for(var key in param)
    {
        if(param.hasOwnProperty(key))
        {
            tmp = tmp.replaceAll("\\"+chr+"\\{"+key+"\\}", param[key]);
        }
    }
    return tmp;
};

/**
 * 扩展Object对象
 * 设置一个属性
 * @param key 属性名
 * @param value 属性值
 */
Object.prototype.put = function(key, value)
{
    this[key] = value;
};

/**
 * 扩展Object对象
 * 获取一个属性
 * @param key 属性名
 * @return 返回key所对应的属性,如果没有返回null
 */
Object.prototype.get = function(key)
{
    return this[key] || null;
};

/**
 * 扩展Object对象
 * 删除一个属性
 * @param key 属性名
 */
Object.prototype.remove = function(key)
{
    if(typeof(this[key]) != "undefined")
        delete this[key];
};

/**
 * 扩展Object对象
 * clone对象
 * @param Boolean isDeep 是否为深度复制
 * @return Object o;
 */
Object.prototype.clone = function(isDeep){
    var o = new Object();
    for(var key in this){
        if(this.hasOwnProperty(key)){
            if(isDeep){
                if(this[key] instanceof Object){
                    o[key] = this[key].clone();
                }else{
                    o[key] = this[key];
                }
            }else{
                o[key] = this[key];
            }
        }
    }
    return o;
};


/**
 * 将对象序列化成字符串
 * @return String 字符串
 */
Object.prototype.toString = function()
{
    var tmp = [];
    var _type = "";
    var _value = null;
    for(var key in this){
        if(this.hasOwnProperty(key)){
            _value = this[key];
            _type = typeof(_value);
            if("string" == _type){ //字符串
                tmp.push('"' + key + '":"'+ _value +'"');
            }else if("number" == _type){ //数字
                tmp.push('"' + key + '":'+ _value);
            }else if("boolean" == _type){ //布尔型
                tmp.push('"' + key + '":'+ _value);
            }else if("undefined" == _type){ //undefined
                tmp.push('"' + key + '":'+ _value);
            }else{ //other
                if(null === _value){
                    tmp.push('"' + key + '":'+ _value);
                }else if(NaN === _value){
                    tmp.push('"' + key + '":'+ _value);
                }else if(_value instanceof Function){                    
                    tmp.push('"' + key + '":'+ (((_value.toString()).replaceAll("[\\n\\r]", "")).replaceAll("[\\s ]+", " ")));
                }else if(_value instanceof Array){
                    tmp.push('"' + key + '":'+ _value.toString());
                }else if(_value instanceof Object){
                    tmp.push('"' + key + '":'+ _value.toString());
                }else{
                    tmp.push('"' + key + '":'+ _value.toString());
                }
            }
        }
    }
    
    return '{' + tmp.join(",") + '}';
};

/**
 * 将数组序列化为字符串
 * @return String 字符串
 */ 
Array.prototype.toString = function(){
    var tmp = [];
    var _type = "";
    var _value = null;
    var size = this.length;
    for(var i = 0; i < size; i++){
        _value = this[i];
        _type = typeof(_value);
        if("string" == _type){ //字符串
            tmp.push('"'+ _value +'"');
        }else if("number" == _type){ //数字
            tmp.push(_value);
        }else if("boolean" == _type){ //布尔型
            tmp.push(_value);
        }else if("undefined" == _type){ //undefined
            tmp.push(_value);
        }else{ //other
            if(null === _value){
                tmp.push(_value);
            }else if(NaN === _value){
                tmp.push(_value);
            }else if(_value instanceof Function){                    
                tmp.push((((_value.toString()).replaceAll("[\\n\\r]", "")).replaceAll("[\\s ]+", " ")));
            }else if(_value instanceof Array){
                tmp.push(_value.toString());
            }else if(_value instanceof Object){
                tmp.push(_value.toString());
            }else{
                tmp.push(_value.toString());
            }
        }
    }
    
    return '[' + tmp.join(",") + ']';
};

/**
 * 格式化日期对象
 * @param fmt 格式 %y%M%d%h%m%s%i[%w%W%a%A]
 * @param isFill 是否补0
 * @return 格式化的日期串
 */
Date.prototype.format = function(fmt, isFill)
{
    var year = "" + this.getFullYear();
    var month = "" + (this.getMonth() + 1);
    var date = "" + this.getDate();
    var hour = "" + this.getHours();
    var minute = "" + this.getMinutes();
    var second = "" + this.getSeconds();
    var miSec = "" + this.getMilliseconds();
    var day = this.getDay();
    var cn_weeks = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"];
    var cn_weeks_abbr = ["日", "一", "二", "三", "四", "五", "六"];
    var en_weeks = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
    var en_weeks_abbr = ["Sun.", "Mon.", "Tues.", "Wed.", "Thur.", "Fri.", "Sat."];
    isFill = typeof(isFill) == "boolean" ? isFill : true;
    fmt = fmt || "%y%M%d%h%m%s%i %w";
    fmt = fmt.replace("%y", year);
    fmt = fmt.replace("%M", isFill ? month.fillBefore("0", 2) : month);
    fmt = fmt.replace("%d", isFill ? date.fillBefore("0", 2) : date);
    fmt = fmt.replace("%h", isFill ? hour.fillBefore("0", 2) : hour);
    fmt = fmt.replace("%m", isFill ? minute.fillBefore("0", 2) : minute);
    fmt = fmt.replace("%s", isFill ? second.fillBefore("0", 2) : second);
    fmt = fmt.replace("%i", isFill ? miSec.fillBefore("0", 3) : miSec);
    fmt = fmt.replace("%w", cn_weeks[day]);
    fmt = fmt.replace("%W", en_weeks[day]);
    fmt = fmt.replace("%a", cn_weeks_abbr[day]);
    fmt = fmt.replace("%A", en_weeks_abbr[day]);
    return fmt;
};

/**
 * 将字符串解析成日期对象
 * @param str 需要解析的字符串
 * @param fmt 日期格式
 * @return 日期对象
 */
Date.prototype.parseDate = function(str, fmt)
{
    return this.validDate(str, fmt).date;
};

/**
 * 校验字符串是否为日期格式
 * @param str 需要校验的字符串
 * @param fmt 日期格式
 * @return Object 返回校验后的布尔值和日期对象
 */
Date.prototype.validDate = function(str, fmt)
{
    var tmp = "";
    fmt = fmt || "%y%M%d%h%m%s";
    tmp = fmt;
    fmt = fmt.replace("%y", "(\\d{4})");
    fmt = fmt.replace("%M", "(\\d{1,2})");
    fmt = fmt.replace("%d", "(\\d{1,2})");
    fmt = fmt.replace("%h", "(\\d{1,2})");
    fmt = fmt.replace("%m", "(\\d{1,2})");
    fmt = fmt.replace("%s", "(\\d{1,2})");
    fmt = fmt.replace("%i", "(\\d{1,3})");
    fmt = fmt.replace("%w", "(星期[日|一|二|三|四|五|六])");
    fmt = fmt.replace("%W", "(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday)");
    fmt = fmt.replace("%a", "(日|一|二|三|四|五|六)");
    fmt = fmt.replace("%A", "(Sun\\.|Mon\\.|Tues\\.|Wed\\.|Thur\\.|Fri\\.|Sat\\.)");
    var regExp = new RegExp("^" + fmt + "$");
    var group = regExp.exec(str);
    var _year, _month, _date, _hour, _minute, _second, _millisecond;
    var yIndex = getIndex("y", tmp);
    var MIndex = getIndex("M", tmp);
    var dIndex = getIndex("d", tmp);
    var hIndex = getIndex("h", tmp);
    var mIndex = getIndex("m", tmp);
    var sIndex = getIndex("s", tmp);
    var iIndex = getIndex("i", tmp);
    var isUndefined = (undefined === yIndex
                    && undefined === MIndex
                    && undefined === dIndex
                    && undefined === hIndex
                    && undefined === mIndex
                    && undefined === sIndex
                    && undefined === iIndex);
    var _is = false;
    var d = new Date();
    if (null != group)
    {
        group.shift();
        _year = undefined === yIndex ? d.getFullYear() : parse(group[yIndex]);
        _month = undefined === MIndex ? d.getMonth() : parse(group[MIndex])-1;
        _date = undefined === dIndex ? d.getDate() : parse(group[dIndex]);
        _hour = undefined === hIndex ? d.getHours() : parse(group[hIndex]);
        _minute = undefined === mIndex ? d.getMinutes() : parse(group[mIndex]);
        _second = undefined === sIndex ? d.getSeconds() : parse(group[sIndex]);
        _millisecond = undefined === iIndex ? d.getMilliseconds() : parse(group[iIndex]);
        d = new Date(_year, _month, _date, _hour, _minute, _second, _millisecond);
        _is = (false === isUndefined) && ((d.getFullYear()===_year)
            && (d.getMonth() === _month)
            && (d.getDate() === _date)
            && (d.getHours() === _hour)
            && (d.getMinutes() === _minute)
            && (d.getSeconds() === _second)
            && (d.getMilliseconds() === _millisecond));
    }
    function parse(v)
    {
        return typeof(v) == "undefined" ? 0 : parseInt(v, 10);
    }
    function getIndex(flag, fmt)
    {
        var tmp = fmt.replace(/[^%yMdhmsi]+/g, "");
        var arr = tmp.split("%");
        var size = arr.length;
        for(var i = 1; i < size; i++)
        {
            if(arr[i] == flag)
            {
                return (i - 1);
            }
        }
        return undefined;
    }
    return {isValid : _is, date : d};
};

/**
 * 判断是否是闰年
 * @return 集合(是否是闰年，各月份的天数集，当前月的天数)
 */
Date.prototype.leapYear = function()
{
    var _days = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
    var _is = false;
    var _d = 365;
    if ((this.getFullYear() % 4 == 0 && this.getFullYear() % 100 != 0) || this.getFullYear() % 400 == 0)
    {
        _days.splice(1,1,29);
        _is = true;
        _d = 366;
    }
    else
    {
        _days.splice(1,1,28);
        _is = false;
        _d = 365;
    }
    return {isLeapYear:_is, days:_days, yearDays:_d, monthDays:_days[this.getMonth()]};
};

/**
 * 日期比较
 * @param interval 间隔参数
 *        y 年
 *        q 季度
 *        n 月
 *        d 日
 *        w 周
 *        h 小时
 *        m 分钟
 *        s 秒
 *        i 毫秒
 * @param date 比较日期
 * @return 差值
 */
Date.prototype.dateDiff = function(interval, date)
{
    var diff = 0;
    switch(interval)
    {
        case 'y':
            diff = date.getFullYear() - this.getFullYear();
            break;
        case 'q':
            diff = ((date.getMonth() + 1) + ((date.getFullYear() - this.getFullYear()) * 12) - (this.getMonth() + 1)) / 3;
            break;
        case 'n':
            diff = (date.getMonth() + 1) + ((date.getFullYear() - this.getFullYear()) * 12) - (this.getMonth() + 1);
            break;
        case 'd':
            diff = (date - this) / 86400000;
            break;
        case 'w':
            diff = (date - this) / (86400000 * 7);
            break;
        case 'h':
            diff = (date - this) / 3600000;
            break;
        case 'm':
            diff = (date - this) / 60000;
            break;
        case 's':
            diff = (date - this) / 1000;
            break;
        case 'i':
            diff = date.getTime() - this.getTime();
            break;
        default:
            diff = date.getTime() - this.getTime();
            break;
    }
    return diff;
};

/**
 * 日期相加
 * @param interval 间隔参数
 *        y 年
 *        q 季度
 *        n 月
 *        d 日
 *        w 周
 *        h 小时
 *        m 分钟
 *        s 秒
 *        i 毫秒
 * @param num 差值
 * @return 相加后的日期
 */
Date.prototype.dateAdd = function(interval, num)
{
    switch(interval)
    {
        case 'y':
            this.setFullYear(this.getFullYear() + num);
            break;
        case 'q':
            this.setMonth(this.getMonth() + (num * 3));
            break;
        case 'n':
            this.setMonth(this.getMonth() + num);
            break;
        case 'd':
            this.setDate(this.getDate() + num);
            break;
        case 'w':
            this.setDate(this.getDate() + (num * 7));
            break;
        case 'h':
            this.setHours(this.getHours() + num);
            break;
        case 'm':
            this.setMinutes(this.getMinutes() + num);
            break;
        case 's':
            this.setSeconds(this.getSeconds() + num);
            break;
        case 'i':
            this.setMilliseconds(this.getMilliseconds() + num);
            break;
        default:
            this.setMilliseconds(this.getMilliseconds() + num);
            break;
    }
    return this;
};
/**
 * 用户环境检测
 */
var UA = (function(){
    function getVersion(ua, regExp, index, defVal){
        var result = ua.match(regExp);
        var val = defVal || -1;
        if(null != result){
            val = result[index] || val;
            if(val.indexOf("_") != -1){
                val = val.replace("_", ".");
            }
        }
        return +val;
    };
    //userAgent
    var ua = navigator.userAgent.toLowerCase();

    //检测平台
    var linux = (ua.indexOf("linux") != -1);
    var mac_os = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os") != -1);
    var windows = (ua.indexOf("windows") != -1);
    var windows_ce = (ua.indexOf("windows ce") != -1);
    var windows_nt = (ua.indexOf("windows nt") != -1);
    var windows_xp = (ua.indexOf("windows xp") != -1);
    var iphone_os = (ua.indexOf("iphone os") != -1);
    var iphone = /iphone\;/.test(ua);
    var ipod = /ipod\;/.test(ua);
    var ipad = /ipad\;/.test(ua);
    var android = (ua.indexOf("android") != -1);
    var blackberry = (ua.indexOf("blackberry") != -1);
    var iemobile = (ua.indexOf("iemobile") != -1);
    var symbian_os = (ua.indexOf("symbianos") != -1);
    var s60 = (ua.indexOf("series60") != -1);


    //检测平台版本
    var linux_version = -1;
    var mac_os_version = getVersion(ua, /mac os x[\s ]?(\d+(_\d+)?)/, 1);
    var iphone_os_version = getVersion(ua, /iphone os[\s ]?(\d+(_\d+)?)/, 1); +(iphone_os ? (ua.match(/iphone os ([\d_]+)/))[1] || -1 : -1);
    var windows_version = getVersion(ua, /Windows[\s ]?(\d+)/, 1);
    var windows_nt_version = (windows_nt ? getVersion(ua, /windows nt[\s ]?([\d\.]+)/, 1, 4.0) : (windows_xp ? 5.1 : -1));
    var android_version = getVersion(ua, /android[\s ]?(\d+(\.\d+)?)/, 1);
    var iemobile_version = getVersion(ua, /iemobile[\s ]?(\d+(\.\d+)?)/, 1);
    var symbian_os_version = getVersion(ua, /symbianos\/(\d+(\.\d+)?)/, 1);
    var s60_version = getVersion(ua, /series60\/(\d+(\.\d+)?)/, 1);
    
    //检测浏览器
    var ie = getVersion(ua, /msie[\s \/]?(\d+(\.\d+)?)/, 1);
    var chrome = getVersion(ua, /chrome[\s \/]?(\d+(\.\d+)?)/, 1);
    var safari = getVersion(ua, /version\/(\d+)[\w\W]+safari/, 1);
    var firefox = getVersion(ua, /firefox[ \/](\d+(\.\d+)?)/, 1);
    var maxthon = getVersion(ua, /maxthon[ \/](\d+(\.\d+)?)/, 1);
    var netscape = getVersion(ua, /(netscape[\d]*|navigator)\/(\d+(\.\d+)?)/, 2);
    var myie = getVersion(ua, /myie(\d+)/, 1);
    var opera = getVersion(ua,/(opera[\s ]?|opera\/)(\d+(\.\d+)?)/, 2);
    var nokia = getVersion(ua, /browserng\/(\d+(\.\d+)?)/, 1);
    var qqbrowser = getVersion(ua, /qqbrowser\/(\d+(\.\d+)?)/, 1);
    
    var o = {
        "Platform" : {
            "Linux" : linux,
            "MacOS" : mac_os,
            "Windows" : windows,
            "WindowsCE" : windows_ce,
            "WindowsNT" : windows_nt,
            "WindowsXP" : (windows_xp || (5.1 == windows_nt_version)),
            "iPhoneOS" : iphone_os,
            "iPhone" : iphone,
            "iPod" : ipod,
            "iPad" : ipad,
            "Android" : android,
            "BlackBerry" : blackberry,
            "IEMobile" : iemobile,
            "SymbianOS" : symbian_os,
            "S60" : s60
        },
        "Version" : {
            "Linux" : linux_version,
            "MacOS" : mac_os_version,
            "iPhoneOS" : iphone_os_version,
            "Windows" : windows_version,
            "WindowsNT" : windows_nt_version,
            "Android" : android_version,
            "IEMobile" : iemobile_version,
            "SymbianOS" : symbian_os_version,
            "S60" : s60_version
        },
        "Browser" : {
            "ie" : ie,
            "chrome" : chrome,
            "safari" : safari,
            "firefox" : firefox,
            "maxthon" : maxthon,
            "netscape" : netscape,
            "myie" : myie,
            "opera" : opera,
            "nokia" : nokia,
            "QQBrowser" : qqbrowser
        }
    };
    
    var arr = [];
    
    for(var key in o){
        if(o.hasOwnProperty(key)){
            if(o[key] instanceof Object){
                for(var i in o[key]){
                    if(o[key].hasOwnProperty(i)){
                        arr.push(key + "::" + i + " = " + o[key][i]);
                    }
                }
            }
        }
    }
    
    o["info"] = arr;
    return o;
})();

var XLib = window["XLib"] = {
    version : "1.0.0.149",
    /**
     * 编码
     * @param str 需要编码的字符串
     * @return 编码后的字符串
     */
    encode : function(str)
    {
        return encodeURIComponent(str);
    },
    /**
     * 解码
     * @param str 需要解码的字符串
     * @return 解码后的字符串
     */
    decode : function(str)
    {
        return decodeURIComponent(str);
    },
    /**
     * 获取时间戳
     * @return  时间戳
     */
    getTimeStamp : function()
    {
        return (new Date()).getTime();
    },
    /**
     * 获取相对位置
     * @param ref 参考节点
     * @return {x,y}
     */
    getPosition : function(ref)
    {
        var _x = 0;
        var _y = 0;
        while(null != ref)
        {
            _x += ref.offsetLeft;
            _y += ref.offsetTop;
            ref = ref.offsetParent;
        }
        return {x:_x, y:_y};
    },
    /**
     * cookie接口
     * method : get
     *          set
     *          remove
     */
    Cookie : {
        /**
         * 设置cookie
         * @param key 键名
         * @param value 键值
         * @param domain 域
         * @param path 路径
         * @param expires 过期时间（毫秒）
         * @throws 参数错误
         */
        set : function(key, value, domain, path, expires)
        {
            var args = arguments;
            var size = args.length;
            domain = domain || document.domain;
            path = path || "/";
            expires = new Date().dateAdd("i", (expires||0)).toGMTString();
            switch (size)
            {
                case 2:
                    document.cookie = key + "=" + XLib.encode(value) + "; path=/;";
                    break;
                case 3:
                    document.cookie = key + "=" + XLib.encode(value) + "; path=/; domain=" + domain;
                    break;
                case 4:
                    document.cookie = key + "=" + XLib.encode(value) + "; path=" + path + "; domain="+domain;
                    break;
                case 5:
                    document.cookie = key + "=" + XLib.encode(value) + "; path=" + path + "; domain="+domain+"; expires=" + expires;
                    break;
                default:
                    throw new Error("设置cookie时参数错误！");
            }
        },
        /**
         * 获取cookie值
         * @param key 键名
         * @return cookie值,如果没有返回null
         */
        get : function(key)
        {
            var _cookie = document.cookie;
            var items = _cookie.split("; ");
            var item = [];
            var size = items.length;
            for (var i = 0; i < size; i++)
            {
                item = items[i].split("=");
                if(key == item[0] && item.length == 2)
                {
                    return XLib.decode(item[1]);
                }
            }
            return null;
        },
        /**
         * 删除cookie值
         * @param key 键名
         * @param domain 域
         * @param path 路径
         */
        remove : function(key, domain, path)
        {
            this.set(key, "", domain, path, -1);
        }
    },
    /**
     * url处理接口
     * @method getParameter
     *         getParameterValues
     *         parseURL
     */
    URL : {
        /**
         * 获取URL参数
         * @param key 键名
         * @param url 自定义的URL，可不传，默认为当前的URL
         * @return URL参数,如果没有匹配返回null
         */
        getParameter : function(key, url)
        {
            var values = this.getParameterValues(key, url || document.location.search);
            var size = values.length;
            var item = size > 0 ? values[size - 1] : null;
            values = null;
            return item;
        },
        /**
         * 获取URL参数集
         * @param key 键名
         * @param url 自定义的URL，可不传，默认为当前的URL
         * @return 返回匹配key的所有值
         */
        getParameterValues : function(key, url)
        {
            var search = url || document.location.search;
            var pattern = new RegExp("[?&]"+key+"\=([^&#]*)", "g");
            var matcher = null;
            var ret = [];
            
            while(null != (matcher = pattern.exec(search)))
            {
                ret.push(XLib.decode(matcher[1]));
            }
            pattern = null;
            matcher = null;
            return ret;
        },
        /**
         * 解析URL
         * @param url 自定义的URL，可不传，默认为当前的URL
         * @return 对象(url, querystring对象, hash)
         */
        parseURL : function(url)
        {
            url = url || document.location.href;
            var pattern = /[\?&]([^\?&=#]+)=([^&#]*)/g;
            var matcher = null;
            var items = {};
            var ret = {};
            var _u = url.split("?");
            var _hash = url.split("#");
            
            while(null != (matcher = pattern.exec(url))){
                items[matcher[1]] = matcher[2];
            }
            pattern = null; matcher = null;
            ret = {local:_u[0], qs:items, hash:(_hash.length > 1 ? _hash[1] : null)};
            return ret;
        },
        /**
         * 添加参数
         * @param url
         * @param params
         * @return 添加参数后的URL
         */
        append : function(url, params)
        {
            if(params)
            {
                return url + (url.indexOf('?') === -1 ? '?' : '&') + params;
            }
            else
            {
                return url;
            }
        },
        /**
         * 过滤脚本
         * @param String str 字符串
         * @return String str 过滤后的字符串
         */
        filterScript:function(str){
            str = str || "";
            str = str.replace(/<.*>/g, ""); //过滤标签注入
            str = str.replace(/(java|vb|action)script/gi, ""); //过滤脚本注入
            str = str.replace(/[\"\'][\s ]*([^=\"\'\s ]+[\s ]*=[\s ]*[\"\']?[^\"\']+[\"\']?)+/gi, ""); //过滤HTML属性注入
            str = str.replace(/[\s ]/g, "&nbsp;"); //替换空格
            return str;
        }
    },
    DOM : {
        /**
         * 根据ID获取元素对象
         * @param id 元素ID或对象
         * @return 元素对象,如果没有匹配返回null
         */
        $E : function(id, parent)
        {
            var pNode = parent || document;
            var ret = null;
            switch(typeof(id))
            {
                case "string":
                    ret = pNode.getElementById(id);
                break;
                case "object":
                    ret = id;
                break;
            }
            return ret;
        },
        /**
         * 根据标签名获取元素集
         * @param tagName 标签名
         * @param parentNode 父级
         * @return 元素集
         */
        $T : function(tagName, parentNode)
        {
            var p = parentNode || document;
            return p.getElementsByTagName(tagName);
        },
        /**
         * 建立一个新的元素
         * @param tag
         * @return 新建立的元素
         */
        $C : function(tag)
        {
            return document.createElement(tag);
        },
        /**
         * 建立一个带name属性的新元素
         * @param tag
         * @param name
         * @return 新建立的元素
         */
        $CN : function(tag, name)
        {
            if(UA.Browser.ie > 0)
            {
                return document.createElement('<' + tag + ' name=' + name + '>');
            }
            else
            {
                var el = document.createElement(tag);
                el.setAttribute("name", name);
                return el;
            }
        },
        /**
         * 建立一个新的文本节点
         * @param text 文本内容
         * @return 新建立的文本节点
         */
        $X : function(text)
        {
            return document.createTextNode(text);
        },
        /**
         * 追加一个新的节点
         * @param cNode 要追加的节点
         * @param pNode 父节点
         * @return 追加后的节点
         */
        $A : function(cNode, pNode)
        {
            var p = pNode || document.body || document.documentElement;
            return p.appendChild(cNode);
        },
        /**
         * 删除一个节点
         * @param cNode 要删除的节点
         * @param pNode 父节点
         * @return 删除后的节点
         */
        $D : function(cNode, pNode)
        {
            var p = pNode || document.body || document.documentElement;
            return p.removeChild(cNode);
        },
        /**
         * 替换一个节点
         * @param nNode 新节点
         * @param oNode 参考节点
         * @return 替换后的节点,如果参考节点没有父级节点则返回null
         */
        $R : function(nNode, oNode)
        {
            var p = oNode.parentNode;
            if(null != p)
            {
                return p.replaceChild(nNode, oNode);
            }
            return null;
        },
        /**
         * 插入一个新的节点
         * @param newNode 新节点
         * @param refNode 参考节点
         * @return 插入新节点后的节点, 如果没参考节点没有父级节点则返回null
         */
        $I : function(newNode, refNode)
        {
            var p = refNode.parentNode;
            if(null != p)
            {
                return p.insertBefore(newNode, refNode);
            }
            return null;
        },
        /**
         * 在当前节点后插入一个新的节点
         * @param newNode 新节点
         * @param refNode 参考节点
         * @return 插入新节点后的节点, 如果没参考节点没有父级节点则返回null
         */
        $IA : function(newNode, refNode)
        {
            var p = refNode.parentNode;
            if(null != p)
            {
                while(null != (refNode = refNode.nextSibling))
                {
                    if(refNode.nodeType && 1 == refNode.nodeType)
                    {
                        return XLib.DOM.$I(newNode, refNode);
                    }
                }

                return XLib.DOM.$A(newNode, p);
            }
            return null;
        },
        /**
         * HTML属性转换
         */
        attrTrans :
        {
            "for" : "htmlFor",
            "class" : "className",
            "readonly" : "readOnly",
            "maxlength" : "maxLength",
            "cellspacing" : "cellSpacing",
            "rowspan" : "rowSpan",
            "colspan" : "colSpan",
            "tabindex" : "tabIndex",
            "usemap" : "useMap",
            "frameborder" : "frameBorder"
        },
        /**
         * 根据属性名获取节点集
         * @param attrName 属性名
         * @param parentNode 父级节点
         * @return Array
         */
        getElementsByAttrName : function(attrName, parentNode)
        {
            var strAttr = this.attrTrans[attrName] || attrName;
            var p = parentNode || document;
            var items = this.$T("*", p);
            var size = items.length;
            var arr = [];
            for(var i = 0; i < size; i++)
            {
                if(null != items[i].getAttribute(attrName) || null != items[i].getAttribute(strAttr))
                {
                    arr.push(items[i]);
                }
            }
            return arr;
        },
        /**
         * 根据属性值获取节点集
         * @param attrName 属性名
         * @param value 属性值
         * @param parentNode 父级节点
         * @param _isFull 是否全值匹配
         * @return Array
         */
        getElementsByAttr : function(attrName, value, parentNode, _isFull)
        {
            var strAttr = this.attrTrans[attrName] || attrName;
            var items = this.getElementsByAttrName(attrName, parentNode || null);
            var size = items.length;
            var arr = [];
            var item = null;
            var isFull = typeof(_isFull) == "boolean" ? _isFull : true;
            var attr = null;
            var p1 = new RegExp("^(" + value + ")$");
            var p2 = new RegExp("^(" + value + ")[\s ]+");
            var p3 = new RegExp("[\s ]+(" + value + ")$");
            var p4 = new RegExp("[\s ]+(" + value + ")[\s ]+");
            for(var i = 0; i < size; i++)
            {
                item = items[i];
                attr = (item.getAttribute(attrName) || item.getAttribute(strAttr));
                if(isFull)
                {
                    if(value == attr)
                    {
                        arr.push(item);
                    }
                }
                else
                {
                    if(p1.test(attr) || p2.test(attr) || p3.test(attr) || p4.test(attr))
                    {
                        arr.push(item);
                    }
                }
            }
            p1 = null; p2 = null; p3 = null; p4 = null;
            return arr;
        },

        /**
         * 根据属性名获取节点集
         * @param className 类
         * @param parentNode 父级节点
         * @param _isFull 是否全值匹配
         * @return Array
         */
        getElementsByClassName : function(className, parentNode, _isFull)
        {
            var isFull = typeof(_isFull) == "boolean" ? _isFull : true;
            var items = this.getElementsByAttr("class", className, parentNode || null, isFull);
            return items;
        },
        /**
         * 获取注释片断
         * @param refNode 参考节点
         * @param deep 深度遍历
         * @return 注释片断
         */
        getCommentFragment : function(refNode, deep)
        {
            var bDeep = deep || false;
            var children = refNode.childNodes;
            var size = children.length;
            var comments = [];
            for(var i = 0; i < size; i++)
            {

                if(8 === children[i].nodeType)
                {
                    comments.push(children[i]);
                }
                else if(1 === children[i].nodeType && bDeep)
                {
                    comments = comments.concat(this.getCommentFragment(children[i], bDeep));
                }
            }
            children = null;
            return comments;
        },
        /**
         * 获取注释内容
         * @param refNode 参考节点
         * @param deep 深度遍历
         * @return 注释内容
         */
        getCommentData : function(refNode, deep)
        {
            var comments = this.getCommentFragment(refNode, deep);
            var size = comments.length;
            var pattern = /^id=\"[^\"]+\"/;
            var data = [];
            for(var i = 0; i < size; i++)
            {
                data.push((comments[i].data).replace(pattern, ""));
            }
            pattern = null;
            comments = null;
            return data;
        },
        /**
         * 根据ID获取注释片断
         * @param refNode 参考节点
         * @param deep 深度遍历
         * @param id 注释ID, <!--id="xxx"
         * @return 注释片断
         */
        getCommentFragmentById : function(refNode, deep, id)
        {
            var comments = this.getCommentFragment(refNode, deep);
            var size = comments.length;
            var pattern = new RegExp("^id=\"("+id+")\"");
            var node = null;
            for(var i = 0; i < size; i++)
            {
                if(pattern.test(comments[i].data))
                {
                    node = comments[i];
                    break;
                }
            }
            pattern = null;
            comments = null;
            return node;
        },
        /**
         * 根据ID获取注释内容
         * @param refNode 参考节点
         * @param deep 深度遍历
         * @param id 注释ID, <!--id="xxx"
         * @return 注释内容
         */
        getCommentDataById : function(refNode, deep, id)
        {
            var comments = this.getCommentFragment(refNode, deep);
            var size = comments.length;
            var pattern = new RegExp("^id=\"("+id+")\"");
            var data = null;
            for(var i = 0; i < size; i++)
            {
                if(pattern.test(comments[i].data))
                {
                    data = comments[i].data;
                    data = data.replace(pattern, "");
                    break;
                }
            }
            pattern = null;
            comments = null;
            return data;
        },
        isReady : false, //是否准备
        handlerList : [], //列表
        /**
         * DOM加载
         * @param handler 事件函数
         * @param args 参数
         */
        ready : function(handler, args)
        {
            XLib.DOM.handlerList.push({"handler":handler, "args":args});
            
            if(XLib.DOM.isReady){ //已经准备OK，直接调用。
                XLib.DOM.isReady = true;
                XLib.DOM._callReadyHandler(0);
            }else{
                if(document.addEventListener){
                    document.addEventListener("DOMContentLoaded", function(){
                        document.removeEventListener("DOMContentLoaded", arguments.callee, false);
                            XLib.DOM._callReadyHandler(0);
                    }, false);
                }else{
                    var itv = setInterval(function(){
                        if(!/in/.test(document.readyState)){
                            clearInterval(itv);
                            XLib.DOM._callReadyHandler(0);                            
                        }
                    }, 50);
                }
            }
        },
        /**
         * 调用回调函数
         * @param int index 索引
         */
        _callReadyHandler : function(index)
        {
            XLib.DOM.isReady = true;
            
            var list = XLib.DOM.handlerList;
            var size = list.length;
            var o = null;
            if(size > 0){
                o = list[index];
                o["handler"].apply(null, o["args"]);
                XLib.DOM.handlerList.shift();
                arguments.callee(0);
            }
        },
        /**
         * 获取节点偏移值
         * @param Node node 节点
         * @return Object {int x X轴, int y Y轴}
         */
        getNodeOffset : function(node){
            if(UA.Browser.ie <= 7){//fixed ie6&ie7 calculate error
                var _x = 0;
                var _y = 0;
                while(node){
                    _x += node.offsetLeft;
                    _y += node.offsetTop;
                    if(node == document.body){break;}
                    node = node.parentNode;
                }
                return {x:_x, y:_y};
            }else{ //other browser
                return {x:node.offsetLeft, y:node.offsetTop};
            }
        }
    },
    BOM : {
        /**
         * 获取文档大小
         * @member width 文档宽
         * @member height 文档高
         * @return 返回文档的宽和高
         */
        getDocumentSize : function()
        {
            var viewport = this.getViewportSize();
            var _w = 0;
            var _h = 0;
            if(document.documentElement && document.documentElement.scrollWidth)
            {
                _w = document.documentElement.scrollWidth;
                _h = document.documentElement.scrollHeight;
            }
            else if(document.body && document.body.scrollWidth)
            {
                _w = document.body.scrollWidth;
                _h = document.body.scrollHeight;
            }
            else
            {
                _w = viewport.width;
                _h = viewport.height;
            }
            return {width:_w, height:_h};
        },
        /**
         * 获取视窗大小
         * @member width 视窗宽
         * @member height 视窗高
         * @return 返回视窗的宽和高
         */
        getViewportSize : function()
        {
            var _w = 0;
            var _h = 0;
            if(window.innerWidth)
            {
                _w = window.innerWidth;
                _h = window.innerHeight;
            }
            else if(document.documentElement && document.documentElement.clientWidth)
            {
                _w = document.documentElement.clientWidth;
                _h = document.documentElement.clientHeight;
            }
            else if(document.body && document.body.clientWidth)
            {
                _w = document.body.clientWidth;
                _h = document.body.clientHeight;
            }
            return {width:_w, height:_h};
        },
        /**
         * 获取滚动条的位置
         * @member left 左偏移值
         * @member top 上偏移值
         * @return 返回滚动条的左和上的偏移值
         */
        getScrollPosition : function()
        {
            var _l = 0;
            var _t = 0;
            if(window.innerWidth)
            {
                _l = window.pageXOffset;
                _t = window.pageYOffset;
            }
            else if(document.documentElement && document.documentElement.clientWidth)
            {
                _l = document.documentElement.scrollLeft;
                _t = document.documentElement.scrollTop;
            }
            else if(document.body && document.body.clientWidth)
            {
                _l = document.body.scrollLeft;
                _t = document.body.scrollTop;
            }
            return {left:_l, top:_t};
        },
        /**
         * 获取屏幕大小
         * @member width 屏幕宽
         * @member height 屏幕高
         * @member offsetTop 顶部偏移值
         * @member offsetLeft 左侧偏移值
         * @return 返回屏幕大小及偏移值
         */
        getScreenSize : function()
        {
            var _w = window.screen.width;
            var _h = window.screen.height;
            var _t = window.screenTop || window.screenX;
            var _l = window.screenLeft || window.screenY;
            return {width:_w, height:_h, offsetTop:_t, offsetLeft:_l};
        },
        /**
         * 获取滚动条大小
         * @member width 滚动条宽
         * @member height 滚动条高
         * @return 滚动条大小
         */
        getScrollbarSize : function()
        {
            var inner = XLib.DOM.$C("p");
            var outer =  XLib.DOM.$C("div");
            inner.style.width = "100%";
            inner.style.height = "200px";
            outer.style.position = "absolute";
            outer.style.top = "0px";
            outer.style.left = "0px";
            outer.style.visibility = "hidden";
            outer.style.width = "200px";
            outer.style.height = "150px";
            outer.style.overflow = "hidden";
            XLib.DOM.$A(inner, outer);
            XLib.DOM.$A(outer);
            var w1 = inner.offsetWidth;
            var h1 = inner.offsetHeight;
            outer.style.overflow = "scroll";
            var w2 = inner.offsetWidth;
            var h2 = inner.offsetHeight;
            if(w1 == w2)
            {
                w2 = outer.clientWidth;
            }
            if(h1 == h2)
            {
                h2 = outer.clientWidth;
            }
            XLib.DOM.$D(outer);
            return {width : (w1 - w2), height : (h1 - h2)};
        }
    },
    Drag : {
        /**
         * 拖动
         * @param args ID数组
         */
        drag : function(args)
        {
            var size = args.length;
            for (var i = 0; i < size; i++)
            {
                var tar = XLib.DOM.$E(args[i]);
                var l = XLib.Event.getClientX() - tar.offsetLeft;
                var t = XLib.Event.getClientY() - tar.offsetTop;
                var isDrag = true;

                tar.style.cursor = "default";
                XLib.Event.addEventListener(document, "mousemove", function()
                {
                    var innerArgs = args;
                    var size = innerArgs.length;
                    if (isDrag)
                    {
                        for (var j = 0; j < size; j++)
                        {
                            var innerTar = XLib.DOM.$E(innerArgs[j]);
                            innerTar.style.left = Math.max(XLib.Event.getClientX() - l, 0) + "px";
                            innerTar.style.top = Math.max(XLib.Event.getClientY() - t, 0) + "px";
                        }
                        XLib.Event.preventDefault();
                        XLib.Event.stopPropagation();
                    }
                }, [], false);
                XLib.Event.addEventListener(document, "mouseup", function()
                {
                    isDrag = false;
                }, [], false);
            }
        }
    },
    CSS : {
        /**
         * 从外部引用的css或style标签中获取css属性
         * @param selector 选择符
         * @param attr 属性
         * @return css属性,没有匹配返回null
         */
        getOuterStyle : function(selector, attr)
        {
            var stylesheet = document.styleSheets;
            var size = stylesheet.length;
            var sheet = null;
            var rules = null;
            var ruleSize = 0;
            var rule = null;
            for(var i = 0; i < size; i++)
            {
                sheet = stylesheet.item(i);
                rules = sheet.rules || sheet.cssRules;
                ruleSize = rules.length;
                for(var j = 0; j < ruleSize; j++)
                {
                    rule = rules[j];
                    if(!rule.selectorText)continue;
                    if (selector == rule.selectorText)
                    {
                        return rule.style[attr];
                    }
                }
            }
            return null;
        },
        /**
         * 从外部引用的css或style标签中设置css属性
         * @param selector 选择符
         * @param attr 属性
         * @param value 属性值
         * @return css属性,没有匹配返回null
         */
        setOuterStyle : function(selector, attr, value)
        {
            var stylesheet = document.styleSheets;
            var size = stylesheet.length;
            var sheet = null;
            var rules = null;
            var ruleSize = 0;
            var rule = null;

            outer:
            for(var i = 0; i < size; i++)
            {
                sheet = stylesheet.item(i);
                rules = sheet.rules || sheet.cssRules;
                ruleSize = rules.length;
                inner:
                for(var j = 0; j < ruleSize; j++)
                {
                    rule = rules[j];
                    if(!rule.selectorText)continue;
                    if (selector == rule.selectorText)
                    {
                        rule.style[attr] = value;
                        break outer;
                    }
                }
            }
        },
        /**
         * 动态设置样式
         * @param cssTexts 样式集
         * @param suffix style标签ID后缀(dynamic_style_[suffix])
         *               默认为时间戳。
         * @return DOM
         */
        dynamicStyle : function(cssTexts, suffix)
        {
            var id = "dynamic_style_" + (suffix || XLib.getTimeStamp());
            var style = XLib.DOM.$E(id);
            if(null == style)
            {
                style = XLib.DOM.$C("style");
                style.type = "text/css";
                style.rel = "stylesheet";
                style.setAttribute("id", id);
                XLib.DOM.$A(style, XLib.DOM.$T("head")[0]);
                if(UA.Browser.ie > 0)
                {
                    style.styleSheet.cssText = cssTexts.join("");
                }
                else
                {
                    for(var i = 0; i < cssTexts.length; i++)
                    {
                        style.sheet.insertRule(cssTexts[i], i);
                    }
                }
            }
            return style;
        },
        /**
         * 设置class属性
         * @param node 节点
         * @param className 类
         */
        setClass : function(node, className)
        {
            node.className = className;
        },
        /**
         * 获取class属性
         * @param node 节点
         * @return className / null;
         */
        getClass : function(node)
        {
            return node.className || null;
        },
        /**
         * 获取class属性
         * @param node 节点
         * @return className / null;
         */
        delClass : function(node)
        {
            var cls = this.getClass(node);
            this.setClass(node, "");
            return cls;
        },
        /**
         * 是否存在class
         * @param node 节点
         * @param className 类
         * @return {existed, pattern}
         */
        hasClass : function(node, className)
        {
            var cls = this.getClass(node) || "";
            var p1 = new RegExp("^(" + className + ")$");
            var p2 = new RegExp("^(" + className + ")[\\s ]+");
            var p3 = new RegExp("[\\s ]+(" + className + ")$");
            var p4 = new RegExp("[\\s ]+(" + className + ")[\\s ]+");
            var ps = [p1, p2, p3, p4];
            var size = ps.length;
            var p = null;
            var __has = false;
            var __isAddBlank = false;
            for(var i = 0; i < size; i++)
            {
                p = ps[i];
                if(p.test(cls))
                {
                    __has = true;
                    __isAddBlank = (3 === i);
                    break;
                }
            }
            if(!__has)
            {
                p = null;
            }
            ps = null; p1 = null; p2 = null; p3 = null; p4 = null;
            return {existed:__has, pattern:p, isAddBlank:__isAddBlank};
        },
        /**
         * 添加一个class
         * @param node 节点
         * @param className 类
         */
        addClass : function(node, className)
        {
            var cls = this.getClass(node) || "";
            var has = this.hasClass(node, className);
            if(has.existed)
            {
                cls = cls.replace(has.pattern, (has.isAddBlank ? " " : ""));
            }
            this.setClass(node, ("" == cls ? className : (cls + " " + className)));
        },
        /**
         * 移除一个class
         * @param node 节点
         * @param className 类
         */
        removeClass : function(node, className)
        {
            var cls = this.getClass(node) || "";
            var has = this.hasClass(node, className);
            if(has.existed)
            {
                cls = cls.replace(has.pattern, (has.isAddBlank ? " " : ""));
            }
            this.setClass(node, cls);
        }
    },
    JSON : {
        /**
         * json 对象转换成string
         * @param json 需要转换的对象
         * @return string
         */
        json2string : function(json)
        {
            return json.toString();
        },
        /**
         * 将XML转换为json格式
         * @param xmlDoc
         * @return json
         */
        xml2json : function(xmlDoc)
        {
            var _xml = new XLib.XML();
            var root = xmlDoc.documentElement;
            var tagName = root.tagName;
            var json = {};
            json[tagName] = {};
            json[tagName] = this.$parseAttributes(_xml, json[tagName], root);
            json[tagName] = this.$parseXML(_xml, json[tagName], root);
            _xml = null;
            return json;
        },
        /**
         * 解析节点属性
         * @param _xml
         * @param obj
         * @param node
         * @return obj
         */
        $parseAttributes : function(_xml, obj, node)
        {
            var attrs = _xml.selectNodes(node, "./@*", null);
            var size = attrs.length;
            var attr = null;
            for(var i = 0; i < size; i++)
            {
                attr = attrs[i];
                obj[attr.nodeName] = attr.nodeValue;
            }
            return obj;
        },
        /**
         * 测试节点,是否有多个.
         * @param _xml
         * @param node
         * @param tagName
         * @return true/false
         */
        $testNode : function(_xml, node, tagName)
        {
            var nodes = _xml.selectNodes(node.parentNode, "./" + tagName, null);
            var size = nodes.length;
            nodes = null;
            return size > 1;
        },
        /**
         * 解析XML
         * @param _xml
         * @param obj
         * @param _node
         * @return object
         */
        $parseXML : function(_xml, obj, _node)
        {
            var nodes = _xml.selectNodes(_node, "./*", null);
            var size = nodes.length;
            var node = null;
            var tagName = null;
            var isArray = false;
            if(0 == size)
            {
                node = _xml.selectSingleNode(_node, "./text()");
                if(null != node)
                {
                    obj["nodeValue"] = node.data;
                }
            }
            else
            {
                for(var i = 0; i < size; i++)
                {
                    node = nodes[i];
                    if(3 == node.nodeType) //text node
                    {
                        obj["nodeValue"] = node.nodeValue;
                    }
                    else if(1 == node.nodeType) //element
                    {
                        tagName = node.tagName;
                        isArray = this.$testNode(_xml, node, tagName);
                        if(true === isArray)
                        {
                            if(undefined === obj[tagName])
                            {
                                obj[tagName] = [];
                            }
                            var tmpObj = {};
                            tmpObj = this.$parseAttributes(_xml, tmpObj, node);
                            tmpObj = this.$parseXML(_xml, tmpObj, node);
                            obj[tagName].push(tmpObj);
                            tmpObj = null;
                        }
                        else
                        {
                            obj[tagName] = {};
                            obj[tagName] = this.$parseAttributes(_xml, obj[tagName], node);
                            obj[tagName] = this.$parseXML(_xml, obj[tagName], node);
                        }
                    }
                    else
                    {
                        continue;
                    }
                }
            }
            return obj;
        },
        /**
         * json对象转为xml串
         * @param json
         * @param instruction
         * @return xml string
         */
        json2xml : function(json, instruction)
        {
            var ins = instruction || '<?xml version="1.0" encoding="utf-8" ?>';
            var _xmlStr = '';
            for(var key in json)
            {
                if(json.hasOwnProperty(key))
                {
                    _xmlStr += this.$genNode(key, json[key]);
                }
            }
            return ins + _xmlStr;
        },
        /**
         * 是否使用CDATA
         * @param value
         * @return true/false
         */
        $isUseCDATA : function(value)
        {
            var pattern = /[\&\<\>\'\"]+/g;
            var inc = pattern.test(value);
            pattern = null;
            return inc;
        },
        /**
         * 获取>符号
         * @param str
         * @return "" or ">"
         */
        $getCloseChr : function(str)
        {
            var pattern = /\>$/g;
            var inc = pattern.test(str);
            pattern = null;
            return inc ? "" : ">";
        },
        /**
         * 生成节点
         * @param tagName
         * @param node
         * @return string
         */
        $genNode : function(tagName, node)
        {
            var str = '<'+tagName;
            var value = null;
            var size = 0;
            for(var key in node)
            {
                if(node.hasOwnProperty(key))
                {
                    value = node[key];
                    if(value instanceof Object) //对象
                    {
                        if(undefined !== value.length)
                        {
                            size = value.length;
                            for(var j = 0; j < size; j++)
                            {
                                str += this.$getCloseChr(str) + this.$genNode(key, value[j]);
                            }
                        }
                        else
                        {
                            str += this.$getCloseChr(str) + this.$genNode(key, value);
                        }
                    }
                    else if(value instanceof Array) //数组
                    {
                        size = value.length;
                        for(var i = 0; i < size; i++)
                        {
                            str += this.$getCloseChr(str) + this.$genNode(tagName, value[i]);
                        }
                    }
                    else
                    {
                        if("nodeValue" == key)//节点值
                        {
                            if(this.$isUseCDATA(value))
                            {
                                str += this.$getCloseChr(str) + '<![CDATA['+value+']]>';
                            }
                            else
                            {
                                str += this.$getCloseChr(str) + value;
                            }
                        }
                        else
                        {
                            str += ' ' + key + '="' + value + '"';
                        }
                    }
                }
            }
            str += '</'+tagName+'>';
            return str;
        },
        /**
         * string转换成json
         * @param json 需要转换的string
         * @return json
         */
        string2json : function(str)
        {
            var json = {};
            eval("json = " + str);
            return json;
        }
    },
    /**
     * 事件接口
     * @property _event
     * @method
     */
    Event : {
        _event : null,
        eventListenerList : [],
        getEvent : function()
        {
            if(UA.Browser.ie > 0 || UA.Browser.safari > 0)
            {
                return window.event;
            }
            else
            {
                var func = arguments.callee.caller;
                while(func != null)
                {
                   var arg = func.arguments[0];
                   if(arg)
                   {
                      if(String(arg.constructor).indexOf('Event') > -1)
                      {
                          return arg;
                      }
                   }
                   func=func.caller;
                }
                return null;
            }
        },
        getClientX : function()
        {
            this._event = this.getEvent();
            if(UA.Browser.ie > 0)
            {
                return this._event.clientX;
            }
            else
            {
                return this._event.pageX;
            }
        },
        getClientY : function()
        {
            this._event = this.getEvent();
            if(UA.Browser.ie > 0)
            {
                return this._event.clientY;
            }
            else
            {
                return this._event.pageY;
            }
        },
        getOffsetX : function()
        {
            this._event = this.getEvent();
            if(UA.Browser.ie > 0)
            {
                return this._event.offsetX;
            }
            else
            {
                return this._event.layerX;
            }
        },
        getOffsetY : function()
        {
            this._event = this.getEvent();
            if(UA.Browser.ie > 0)
            {
                return this._event.offsetY;
            }
            else
            {
                return this._event.layerY;
            }
        },
        getKeyCode : function()
        {
            this._event = this.getEvent();
            if(UA.Browser.ie > 0)
            {
                return this._event.keyCode;
            }
            else
            {
                return this._event.which;
            }
        },
        getButton : function()
        {
            this._event = this.getEvent();
            if(UA.Browser.ie > 0)
            {
                return this._event.button;
            }
            else
            {
                return this._event.which;
            }
        },
        getSrcElement : function()
        {
            this._event = this.getEvent();
            if(UA.Browser.ie > 0)
            {
                return this._event.srcElement;
            }
            else
            {
                return (function(e){
                    var n = e._event.target;
                    while (n.nodeType != 1)
                    {
                        n = n.parentNode;
                    }
                    return n;
                })(this);
            }
        },
        /**
         * 清除选择内容
         */
        clearSelection : function()
        {
            try
            {
                window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
            }
            catch(e){}
        },
        /**
         * 阻止事件返回值
         */
        preventDefault : function()
        {
            this._event = this.getEvent();
            if(UA.Browser.ie > 0)
            {
                this._event.returnValue = false;
            }
            else
            {
                this._event.preventDefault();
            }
        },
        /**
         * 阻止事件冒泡
         */
        stopPropagation : function()
        {
            this._event = this.getEvent();
            if(UA.Browser.ie > 0)
            {
                this._event.cancelBubble = true;
            }
            else
            {
                this._event.stopPropagation();
            }
        },
        /**
         * 分发一个事件
         * @param target 事件源
         * @param eventType 事件类型 xxxx
         * @param datatype 事件属性
         * @param data 事件属性
         */
        dispatchEvent : function(target, eventType, datatype, data)
        {
            var obj = XLib.DOM.$E(target);
            var e = null;
            if(UA.Browser.ie > 0)
            {
                e = document.createEventObject();
                e.datatype = datatype;
                e.data = data;
                obj.fireEvent("on" + eventType, e);
            }
            else
            {
                e = document.createEvent("Events");
                e.initEvent(eventType, true, true);
                e.datatype = datatype;
                e.data = data;
                obj.dispatchEvent(e);
            }
        },
        /**
         * 将事件句柄从事件句柄列表中
         * @param type 事件类型
         * @param handler 事件句柄
         * @param args 事件句柄参数
         * @param _isCapture 是否捕获
         * @param _callee 调用的事件句柄
         */
        setEventListener : function(type, handler, args, _isCapture, _callee)
        {
            var listener = this.getEventListener(type, handler, args, _isCapture);
            if(null === listener)
            {
                this.eventListenerList.push({
                    "type" : type,
                    "handler": handler,
                    "args" : args,
                    "isCapture" : _isCapture,
                    "callee" : _callee
                });
            }
        },
        /**
         * 从事件句柄列表中获取事件句柄
         * @param type 事件类型
         * @param handler 事件句柄
         * @param args 事件句柄参数
         * @param _isCapture 是否捕获
         * @param return 事件句柄/null
         */
        getEventListener : function(type, handler, args, _isCapture)
        {
            var list = this.eventListenerList;
            var size = list.length;
            var item = null;
            for(var i = 0; i < size; i++)
            {
                item = list[i];
                if(item["type"] === type
                    && item["handler"] === handler
                        && item["isCapture"] === _isCapture)
                {
                    return item["callee"];
                }
            }
            return null;
        },
        /**
         * 从事件句柄列表中删除事件句柄
         * @param type 事件类型
         * @param handler 事件句柄
         * @param args 事件句柄参数
         * @param _isCapture 是否捕获
         * @param return 删除的事件句柄/null
         */
        delEventListener : function(type, handler, args, _isCapture)
        {
            var list = this.eventListenerList;
            var size = list.length;
            var item = null;
            for(var i = 0; i < size; i++)
            {
                item = list[i];
                if(item["type"] === type
                    && item["handler"] === handler
                        && item["isCapture"] === _isCapture)
                {
                    return this.eventListenerList.splice(i, 1);
                }
            }
            return null;
        },
        /**
         * 添加事件监听
         * @param oTarget 事件源
         * @param type 事件类型
         * @param handler 事件句柄
         * @param args 事件句柄参数
         * @param isCapture 是否捕获
         */
        addEventListener : function(oTarget, type, handler, args, isCapture)
        {
            var _callee = function(){
                handler.apply(XLib.DOM.$E(oTarget), args);
            };
            var _isCapture = isCapture || false;
            this.removeEventListener(oTarget, type, handler, args, isCapture);
            this.setEventListener(type, handler, args, _isCapture, _callee);
            if(UA.Browser.ie > 0)
            {
                XLib.DOM.$E(oTarget).attachEvent("on" + type, _callee);
            }
            else
            {
                XLib.DOM.$E(oTarget).addEventListener(type, _callee, _isCapture);
            }
            _callee = null;
        },
        /**
         * 移除事件监听
         * @param oTarget 事件源
         * @param type 事件类型
         * @param handler 事件句柄
         * @param args 事件句柄参数
         * @param isCapture 是否捕获
         */
        removeEventListener : function(oTarget, type, handler, args, isCapture)
        {
            var _isCapture = isCapture || false;
            var _callee = this.getEventListener(type, handler, args, _isCapture);
            if(null !== _callee)
            {
                if(UA.Browser.ie > 0)
                {
                    XLib.DOM.$E(oTarget).detachEvent("on" + type, _callee);
                }
                else
                {
                    XLib.DOM.$E(oTarget).removeEventListener(type, _callee, _isCapture);
                }
            }
            this.delEventListener(type, handler, args, _isCapture);
            _callee = null;
        },
        /**
         * 移除事件监听
         * @param oTarget 事件源
         * @param type 事件类型
         * @param handler 事件句柄
         * @param args 事件句柄参数
         * @param isCapture 是否捕获
         */
        once : function(oTarget, type, handler, args, isCapture)
        {
            var _callee = function(){
                XLib.Event.removeEventListener(oTarget, type, handler, args, isCapture);
                handler.apply(XLib.DOM.$E(oTarget), args);
            };
            var _isCapture = isCapture || false;
            this.setEventListener(type, handler, args, _isCapture, _callee);
            if(UA.Browser.ie > 0)
            {
                XLib.DOM.$E(oTarget).attachEvent("on" + type, _callee);
            }
            else
            {
                XLib.DOM.$E(oTarget).addEventListener(type, _callee, _isCapture);
            }
            _callee = null;
        }
    }
};
/**
 * 构造函数
 * ajax对象
 * @version 1.5
 */
XLib.Ajax = function()
{
    this.config = {
        method : "POST",
        asynch : true,
        contentType : "application/x-www-form-urlencoded; charset=UTF-8",
        cache : false,
        proxy : null,
        url : null,
        param : null,
        formName : null,
        requestHeader : [],
        headerHandler : null,
        responseHeader : [],
        headerArgs : [],
        handler : null,
        args : [],
        isXML : true,
        timeout : 5000,
        interval : -1,
        tryTimes : -1,
        readyInterval : 50
    };
    this.Request = {
        UNINITIALIZED : 0,
        LOADING       : 1,
        LOADED        : 2,
        INTERACTIVE   : 3,
        COMPLETED     : 4
    };
    this.instance = null;
    this.timeoutId = null;
    this.intervalId = null;
    this.readystatechange = null;
    this.requestTimes = 0;
}
XLib.Ajax.prototype = {
    /**
     * 设置配置参数信息
     * @param config 对象
     * config.method            请求时用的方法,默认为 POST
     * config.asynch            是否为异步,默认为true
     * config.contentType       请求时的Content-Type, 默认为 application/x-www-form-urlencoded; charset=UTF-8
     * config.cache             是否缓存 默认为true
     * config.proxy             代理 默认为null
     * config.url               请求URL
     * config.param             参数
     * config.formName          表单名/表单对象
     * config.requestHeader     需要设置的http头
     * config.headerHandler     获取http头的处理函数
     * config.responseHeader    指定的http头
     * config.headerArgs        获取http头处理函数的参数。
     * config.handler           处理函数
     * config.args              处理函数参数
     * config.isXML             响应类型 true:xml false:text 默认为true
     * config.timeout           请求超时时间
     * config.interval          请求周期
     * config.tryTimes          请求失败时尝试次数
     * config.readyInterval     事件检测周期
     */
    setConfig : function(config)
    {
        config = config || {};
        this.config.method = (config.method || "POST").toUpperCase();
        this.config.asynch = typeof(config.asynch) == "boolean" ? config.asynch : true;
        this.config.contentType = config.contentType || "application/x-www-form-urlencoded; charset=UTF-8";
        this.config.cache = typeof(config.cache) == "boolean" ? config.cache : false;
        this.config.proxy = config.proxy || null;
        this.config.url = config.url || null;
        this.config.param = config.param || null;
        this.config.formName = config.formName || null;
        this.config.requestHeader = config.requestHeader || [];
        this.config.headerHandler = config.headerHandler || null;
        this.config.responseHeader = config.responseHeader || [];
        this.config.headerArgs = config.headerArgs || [];
        this.config.handler = config.handler || null;
        this.config.args = config.args || [];
        this.config.isXML = typeof(config.isXML) == "boolean" ? config.isXML : true;
        this.config.timeout = config.timeout || 5000;
        this.config.interval = config.interval || -1;
        this.config.tryTimes = config.tryTimes || -1;
        this.config.readyInterval = config.readyInterval || 50;
    },
    /**
     * 获取配置信息
     * @return config
     */
    getConfig : function()
    {
        return this.config;
    },
    /**
     * 获取XMLHttpRequest对象实例
     * @return XMLHttpRequest对象
     */
    getInstance : function()
    {
        try
        {
            this.instance = new XMLHttpRequest();
        }
        catch(e1)
        {
            try
            {
                this.instance = new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch(e2)
            {
                try
                {
                    this.instance = new ActiveXObject("Msxml2.XMLHTTP");
                }
                catch (e3)
                {
                    this.instance = null;
                }
            }
        }
        return this.instance;
    },
    /**
     * 重置状态
     */
    resetStatus : function()
    {
        this.clearAbort();
        this.clearCycle();
        this.clearReadyStateChange();
        this.requestTimes = 0;
        this.instance = null;
    },
    /**
     * 捕获异常
     * @param String ex 错误信息
     */
    captureException : function(ex)
    {
        this.resetStatus();
        throw new Error(ex);
    },
    /**
     * 解释处理句柄
     * @param handler 函数句柄
     * @param args 句柄参数
     * @return 句柄
     * @throws handler error
     */
    evalHandler : function(handler, args)
    {
        if (typeof(handler) == "function")
        {
            handler.apply(null, args);
            this.instance = null;
        }
        else if (null != handler)
        {
            this.instance = null;
            this.captureException("Get Handler Error!\n" +
                    "Please check the handler's type.\n" +
                    "The handler's type must be a function or null.");
        }
        this.instance = null;
    },
    /**
     * 获取URL查询串 如果表单名不为空，则遍历表单元素，否则取入参param
     * return URL QueryString
     */
    getQueryString : function()
    {
        var cfg = this.getConfig();
        var strQuery = cfg.param;
        var formName = cfg.formName;
        if(null != formName)
        {
            var qsItems = [];
            var els = [];
            var form = null;
            var el = null;
            var size = 0;
            var tagName = "";
            var type = "";
            qsItems = strQuery ? strQuery.split("&") : [];
            try
            {
                form = typeof(formName) == "object" ? formName : document.forms[formName];
                els = form.elements;
                size = els.length;
                for(var i = 0; i < size; i++)
                {
                    el = els[i];
                    tagName = (el.tagName||"").toUpperCase();
                    type = (el.type||"").toUpperCase();
                    if(!el.name){continue;}
                    switch(tagName)
                    {
                        case "SELECT":
                        case "TEXTAREA":
                            qsItems.push(el.name + "=" + XLib.encode(el.value));
                        break;
                        case "INPUT":
                        {
                            switch(type)
                            {
                                case "TEXT":
                                case "PASSWORD":
                                case "HIDDEN":
                                    qsItems.push(el.name + "=" + XLib.encode(el.value));
                                break;
                                case "RADIO":
                                case "CHECKBOX":
                                {
                                    if(el.checked)
                                    {
                                        qsItems.push(el.name + "=" + XLib.encode(el.value));
                                    }
                                }
                                break;
                            }
                        }
                        break;
                    }
                }
                strQuery = qsItems.join("&");
            }
            catch(e)
            {
                this.captureException("get form data error ! \n " + e.message);
            }
            finally
            {
                qsItems = null;
                els = null;
                form = null;
                el = null;
                size = 0;
                tagName = null;
                type = null;
            }
        }
        return strQuery;
    },
    /**
     * 拼合URL
     * @return 拼合后的URL
     */
    makeURL : function()
    {
        var conf = this.getConfig();
        var url = conf.url || "";
        var proxy = conf.proxy;
        var queryString = this.getQueryString();
        var param = null;
        if("GET" == conf.method)
        {
            url = XLib.URL.append(url, queryString);
        }
        else
        {
            param = queryString;
        }
        if(null != proxy)
        {
            url = XLib.URL.append(proxy, "req_url=" + XLib.encode(url));
        }
        conf = null; queryString = null;
        return {URL:url, DATA:param};
    },
    /**
     * 清除超时请求
     */
    clearAbort : function()
    {
        if(null != this.timeoutId)
        {
            clearTimeout(this.timeoutId);
            this.timeoutId = null;
        }
    },
    /**
     * 清除定时器
     */
    clearCycle : function()
    {
        if(null != this.intervalId)
        {
            clearInterval(this.intervalId);
            this.intervalId = null;
        }
    },
    /**
     * 清除状态定时器
     */
    clearReadyStateChange : function()
    {
        if(null != this.readystatechange)
        {
            clearInterval(this.readystatechange);
            this.readystatechange = null;
        }
    },
    /**
     * 中断请求
     */
    $abort : function(xmlHttp, handler, args)
    {
        var conf = this.getConfig();
        if(conf.timeout > 0)
        {
            var _this = this;
            this.timeoutId = setTimeout(function(){
                xmlHttp.abort();
                if(conf.interval <= 0 &&
                        conf.tryTimes > 0 &&
                            _this.requestTimes < conf.tryTimes)
                {
                    _this.requestTimes++;
                    args.unshift({status:"RETRY", requestTimes:_this.requestTimes, httpStatus:xmlHttp.status, data:null});
                    _this.evalHandler(handler, args);
                    args.shift();
                    _this.$send();
                }
                else
                {
                    args.unshift({status:"TIMEOUT", data:null});
                    _this.evalHandler(handler, args);
                    args.shift();
                }
            }, conf.timeout);
        }
    },
    /**
     * 周期调用
     */
    callSender : function()
    {
        if(this.getConfig().interval > 0)
        {
            var ajax = this;
            this.$send();
            this.intervalId = setInterval(function(){
                ajax.$send();
            }, this.config.interval);
        }
        else
        {
            this.$send();
        }
    },
    /**
     * 获取指定的http头
     */
    $getResponseHeader : function(xhr)
    {
        var headers = this.config.responseHeader;
        var size = headers.length;
        var ret = [];
        for(var i = 0; i < size; i++)
        {
            ret.push({name:headers[i], value:xhr.getResponseHeader(headers[i])});
        }
        return ret;
    },
    /**
     * 请求http头
     */
    $interactive : function(xhr)
    {
        var conf = this.getConfig();
        var handler = conf.headerHandler;
        var args = conf.headerArgs;
        var allHeaders = xhr.getAllResponseHeaders();
        var $headers = this.$getResponseHeader(xhr);
        args.unshift({all:allHeaders, headers:$headers});
        this.evalHandler(handler, args);
        args.shift();
    },
    /**
     * 请求完成
     */
    $completed : function(xhr)
    {
        var conf = this.config;
        var isRX = conf.isXML;
        var handler = conf.handler;
        var args = conf.args;
        this.clearAbort();
        if (200 == xhr.status || 304 == xhr.status || 302 == xhr.status)
        {
            args.unshift({status:xhr.status, data:(isRX ? xhr.responseXML : xhr.responseText)});
            this.evalHandler(handler, args);
            args.shift();
        }
        else
        {
            if(conf.interval <= 0 &&
                    conf.tryTimes > 0 &&
                        this.requestTimes < conf.tryTimes)
            {
                this.requestTimes++;
                args.unshift({status:"RETRY", requestTimes:this.requestTimes, httpStatus:xhr.status, data:null});
                this.evalHandler(handler, args);
                args.shift();
                this.$send();
            }
            else
            {
                args.unshift({status:xhr.status, data:null});
                this.evalHandler(handler, args);
                args.shift();
            }
        }
        conf = null;
        xhr = null;
    },
    /**
     * 设置http头
     * @param xhr  XMLHttpRequest
     */
    $setHeader : function(xhr)
    {
        var headers = this.config.requestHeader;
        var size = headers.length;
        var header = null;
        for(var i = 0; i < size; i++)
        {
            header = headers[i];
            xhr.setRequestHeader(header.name, header.value);
        }
    },
    /**
     * 发送请求
     * @throws 获取XMLHttpRequest失败
     * @throws 运行期发生异常
     */
    $send : function()
    {
        try
        {
            var ajax = this;
            var xhr = this.getInstance();
            var url = this.makeURL();
            var conf = this.getConfig();
            if (null != xhr)
            {                
                xhr.open(conf.method, url.URL, conf.asynch);
                xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");
                if (!conf.cache)
                {
                    xhr.setRequestHeader("No-Cache","1");
                    xhr.setRequestHeader("Pragma","no-cache");
                    xhr.setRequestHeader("Cache-Control","no-cache");
                    xhr.setRequestHeader("Expire","0");
                    xhr.setRequestHeader("Last-Modified","Thu, 1 Jan 1970 00:00:00 GMT");
                    xhr.setRequestHeader("If-Modified-Since","-1");
                }
                xhr.setRequestHeader("Content-Type", conf.contentType);
                this.$setHeader(xhr);
                this.$abort(xhr, conf.handler, conf.args);
                if(conf.asynch)
                {
                    if(null != conf.headerHandler || null != conf.handler)
                    {
                        ajax.readystatechange = setInterval(function()
                        {
                            switch(xhr.readyState)
                            {
                                case ajax.Request.UNINITIALIZED:
                                    break;
                                case ajax.Request.LOADING:
                                    break;
                                case ajax.Request.LOADED:
                                    break;
                                case ajax.Request.INTERACTIVE:
                                    break;
                                case ajax.Request.COMPLETED:
                                    ajax.clearReadyStateChange();
                                    ajax.clearAbort();
                                    if(null != conf.headerHandler){
                                        ajax.$interactive(xhr);
                                    }
                                    if(null != conf.handler){                                        
                                        ajax.$completed(xhr);
                                    }
                                    break;
                            }
                        }, conf.readyInterval);
                    }
                }
                xhr.send(url.DATA);
                if(!conf.asynch && null != conf.handler)
                {
                    this.$completed(xhr);
                }
            }
            else
            {
                this.captureException("Get XMLHttpRequest Object Failure!");
            }
        }
        catch(e)
        {
            this.captureException("An Runtime Error Occurred ! \n\n" + e.message);
        }
    },
    /**
     * 发送请求
     * @param config 对象
     * config.method            请求时用的方法,默认为 POST
     * config.asynch            是否为异步,默认为true
     * config.contentType       请求时的Content-Type, 默认为 application/x-www-form-urlencoded; charset=UTF-8
     * config.cache             是否缓存 默认为true
     * config.proxy             代理 默认为null
     * config.url               请求URL
     * config.param             参数
     * config.formName          表单名
     * config.requestHeader     需要设置的http头
     * config.headerHandler     获取http头的处理函数
     * config.responseHeader    指定的http头
     * config.headerArgs        获取http头处理函数的参数。
     * config.handler           处理函数
     * config.args              处理函数参数
     * config.isXML             响应类型 true:xml false:text 默认为true
     * config.timeout           请求超时时间
     * config.interval          请求周期
     * config.tryTimes          请求失败时尝试次数
     * config.readyInterval     事件检测周期
     */
    sendRequest : function(config)
    {
        this.resetStatus();
        this.setConfig(config);
        this.callSender();
    }
};
/**
 * XPath表达式
 * 构造函数
 * @version 1.1
 * @param xpathText 表示要编译的 XPath 表达式的字符串。
 * @param namespaceURLMapper 从一个名字空间前缀映射到一个全称名字空间 URL 的一个函数。如果不需要这样的映射，则为 null。
 */
XLib.XPathExpression = function(xpathText, namespaceURLMapper)
{
    this.XPathText = xpathText;
    this.namespaceURLMapper = namespaceURLMapper;
    if(document.createExpression)
    {
        this.expression = document.createExpression(xpathText, function(prefix){
            return namespaceURLMapper[prefix];
        });
    }
    else
    {
        this.namespacesString = "";
        if(null != namespaceURLMapper)
        {
            for(var prefix in namespaceURLMapper)
            {
                if(this.namespacesString) this.namespacesString += ' ';
                this.namespacesString += 'xmlns:' + prefix + '="' + namespaceURLMapper[prefix] + '"';
            }
        }
    }
};
XLib.XPathExpression.prototype = {
    /**
     * 获取匹配xpath的节点
     * @param context 文档或元素对象
     * @return NodeList 如果没有找到匹配返回null
     */
    selectNodes : function(context)
    {
        var nodeList = null;
        var result = null;
        var oEvaluator = null;
        var doc = null;
        if(this.expression)
        {
            result = null;
            oEvaluator = new XPathEvaluator();
            result = oEvaluator.evaluate(this.XPathText,
                                      context,
                                      this.namespaceURLMapper,
                                      XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
                                      null);
            var length = result.snapshotLength;
            nodeList = [];
            if(length > 0)
            {
                for(var i = 0; i < length; i++)
                {
                    nodeList.push(result.snapshotItem(i));
                }
            }
            result = null;
            oEvaluator = null;
            context = null;
            return nodeList||[];
        }
        else
        {
            try
            {
                doc = context.ownerDocument;
                if(null == doc)
                {
                    doc = context;
                }
                doc.setProperty("SelectionLanguage", "XPath");
                doc.setProperty("SelectionNamespaces", this.namespacesString);
                if(doc == context)
                {
                    context = doc.documentElement;
                }
                nodeList = context.selectNodes(this.XPathText);
            }
            catch(e)
            {
                throw new Error("对不起，您的浏览器不支XPath！desc = " + e.message);
            }
            finally
            {
                doc = null;
                context = null;
                return nodeList||[];
            }
        }
    },
    /**
     * 获取匹配xpath的的第一个节点
     * @param context 文档或元素对象
     * @return Node 如果没有找到匹配返回null
     */
    selectSingleNode : function(context)
    {
        var node = null;
        var result = null;
        var oEvaluator = null;
        var doc = null;
        if(this.expression)
        {
            result = null;
            oEvaluator = new XPathEvaluator();
            result = oEvaluator.evaluate(this.XPathText,
                                      context,
                                      this.namespaceURLMapper,
                                      XPathResult.FIRST_ORDERED_NODE_TYPE,
                                      null);
            node = result.singleNodeValue;
            result = null;
            oEvaluator = null;
            context = null;
            return node;
        }
        else
        {
            try
            {
                doc = context.ownerDocument;
                if(null == doc)
                {
                    doc = context;
                }
                doc.setProperty("SelectionLanguage", "XPath");
                doc.setProperty("SelectionNamespaces", this.namespacesString);
                if(doc == context)
                {
                    context = doc.documentElement;
                }
                node = context.selectSingleNode(this.XPathText);
                doc = null; context = null;
            }
            catch(e)
            {
                throw new Error("对不起，您的浏览器不支XPath！desc = " + e.message);
            }
            finally
            {
                doc = null;
                context = null;
                return node;
            }
        }
    }
};
/**
 * XML接口
 * 构造函数
 * @version 1.2
 */
XLib.XML = function()
{
    this.XMLDocument = null;
};
XLib.XML.prototype = {
    /**
     * 建立一个新的XML文档
     * @param namespace 命名空间URI
     * @param root 根节点名
     * @param doctype 文档类型
     * @return XML文档
     * @throws 参数错误
     */
    createXMLDocument : function(namespace, root, doctype)
    {
        if(3 != arguments.length)
        {
            throw new Error("建立XML文档时参数错误; length = " + arguments.length);
        }
        var rootTagName = root || "";
        var namespaceURI = namespace || "";
        var docType = doctype || null;
        var xmlDoc = null;
        if(document.implementation && document.implementation.createDocument)
        {
            xmlDoc = document.implementation.createDocument(namespaceURI, rootTagName, docType);
        }
        else
        {
            xmlDoc = new ActiveXObject("MSXML2.DOMDocument");
            if(rootTagName)
            {
                var hasPrefix = rootTagName.indexOf(":") != -1 && namespaceURI;
                var prefix = hasPrefix ? rootTagName.split(":")[0] : "";
                var tagName = hasPrefix ? rootTagName.split(":")[1] : rootTagName;
                var xmlStr = "<" + (hasPrefix ? prefix + ":" : "") + tagName +
                                (hasPrefix ? " xmlns:" + prefix + "=\"" + namespaceURI + "\"" : "") + " />";
                xmlDoc.loadXML(xmlStr);
            }
        }
        this.XMLDocument = xmlDoc;
        xmlDoc = null;
        return this.XMLDocument;
    },
    /**
     * 加载XML文档
     * @param url 文档地址
     * @return XML文档
     */
    load : function(url)
    {
        var xmlDoc = this.createXMLDocument(null, null, null);
        try
        {
            xmlDoc.async = false;
            xmlDoc.load(url);
        }
        catch(e)
        {
            var request = new XMLHttpRequest();
            request.open("GET", url, false);
            request.send(null);
            xmlDoc = request.responseXML;
            request = null;
        }
        finally
        {
            this.XMLDocument = xmlDoc;
            xmlDoc = null;
            return this.XMLDocument;
        }
    },
    /**
     * 加载XML
     * @param xmlStr xml格式字符串
     * @return XML文档
     */
    loadXML : function(xmlStr)
    {
        var xmlDoc = null;
        if("undefined" != typeof(DOMParser))
        {
            var parser = new DOMParser();
            xmlDoc = parser.parseFromString(xmlStr, "application/xml");
            parser = null;
        }
        else if(window.ActiveXObject)
        {
            xmlDoc = this.createXMLDocument(null, null, null);
            xmlDoc.async = false;
            xmlDoc.loadXML(xmlStr);
        }
        else /* for Safari */
        {
            var url = "data:text/xml;charset=utf-8," + encodeURIComponent(xmlStr);
            var request = new XMLHttpRequest();
            request.open("GET", url, false);
            request.send(null);
            xmlDoc = request.responseXML;
            request = null;
        }
        this.XMLDocument = xmlDoc;
        xmlDoc = null;
        return this.XMLDocument;
    },
    /**
     * 获取匹配xpath的节点
     * @param context 文档或元素对象
     * @param xpath XPATH查询串
     * @param namespaceURLMapper 从一个名字空间前缀映射到一个全称名字空间 URL 的一个函数。如果不需要这样的映射，则为 null。
     * @return NodeList 如果没有找到匹配返回null
     */
    selectNodes : function(context, xpathText, namespaceURLMapper)
    {
        var xPath = new XLib.XPathExpression(xpathText, namespaceURLMapper);
        var nodes = xPath.selectNodes(context);
        xPath = null;
        return nodes;
    },
    /**
     * 获取匹配xpath的的第一个节点
     * @param context 文档或元素对象
     * @param xpath XPATH查询串
     * @param namespaceURLMapper 从一个名字空间前缀映射到一个全称名字空间 URL 的一个函数。如果不需要这样的映射，则为 null。
     * @return Node 如果没有找到匹配返回null
     */
    selectSingleNode : function(context, xpathText, namespaceURLMapper)
    {
        var xPath = new XLib.XPathExpression(xpathText, namespaceURLMapper);
        var node = xPath.selectSingleNode(context);
        xPath = null;
        return node;
    },
    /**
     * 将XML文档或节点转成字符串
     * @param node 元素节点
     * @return xml序列化后的字符串
     */
    toString : function(node)
    {
        var fragment = node || this.XMLDocument || null;
        var xmlStr = "";
        if(null != fragment)
        {
            if("undefined" != typeof(XMLSerializer))
            {
                var serializer = new XMLSerializer();
                xmlStr = serializer.serializeToString(fragment);
                serializer = null;
            }
            else if(fragment.xml)
            {
                xmlStr = fragment.xml;
            }
        }
        return xmlStr;
    }
};
/**
 * XSLT处理接口
 * @param _stylesheet 文档对象
 */
XLib.XSLT = function(_stylesheet)
{
    this.stylesheet = _stylesheet;
    this.processor = null;
    if("undefined" != typeof(XSLTProcessor))
    {
        this.processor = new XSLTProcessor();
        this.processor.importStylesheet(this.stylesheet);
    }
};
XLib.XSLT.prototype = {
    transform : function(node, element)
    {
        element = XLib.DOM.$E(element);
        if(this.processor)
        {
            var fragment = this.processor.transformToFragment(node, document);
            element.innerHTML = "";
            element.appendChild(fragment);
        }
        else if("transformNode" in node)
        {
            element.innerHTML = node.transformNode(this.stylesheet);
        }
        else
        {
            throw new Error("XSLT is not supported in this browser!");
        }

    }
};